// 处理设备模板相关业务逻辑（新增、删除、修改和查询当前用户下的设备模板）

//导入EquipmentTemplate数据模型(用户操作数据库中的设备模板表)
const { EquipmentTemplate } = require('../models');
// 导入Joi（用于验证前端传递的请求数据格式）
const Joi = require('joi');
// 导入Sequelize的Op操作符（用于构建复杂查询条件）
const { Op } = require('sequelize');

/**
 * 设备模板查询参数验证规则
 * 用于验证分页查询接口的请求参数
 */
const querySchema = Joi.object({
  // 页码，默认为1，最小为1的整数
  page: Joi.number().integer().min(1).default(1),
  // 每页条数，默认为10，1-100之间的整数
  pageSize: Joi.number().integer().min(1).max(100).default(10),
  // 模板名称，用于模糊查询，允许为空字符串或null
  name: Joi.string().allow('', null),
});

/**
 * 设备模板创建参数验证规则
 * 用于验证创建接口的请求体参数
 */
const createSchema = Joi.object({
  // 模板名称，必填，最大长度100字符
  name: Joi.string().required().max(100).message('模板名称不能为空且长度不超过100字符'),
  // 模板描述，最大长度500字符，允许为空
  description: Joi.string().max(500).allow(null, ''),
  // 设备类型，必填，0-2之间的整数
  equipmentType: Joi.number().integer().min(0).max(2).required().message('设备类型必须为0-2的整数'),
  // 运动方式，最大长度500字符，允许为空
  modeOfMotion: Joi.string().max(500).allow(null, ''),
  // 运动特性，最大长度500字符，允许为空
  kineticCharacteristic: Joi.string().max(500).allow(null, ''),
  // 运行速度，保留两位小数，允许为空
  runningVelocity: Joi.number().precision(2).allow(null),
  // 载荷性质，最大长度200字符，允许为空
  loadProperty: Joi.string().max(200).allow(null, ''),
  // 周围环境，最大长度200字符，允许为空
  surrounding: Joi.string().max(200).allow(null, ''),
  // 设备等级，最大长度100字符，允许为空
  gradeOfEquipment: Joi.string().max(100).allow(null, ''),
  // 是否有备机，0-2之间的整数，默认为0
  standby: Joi.number().integer().min(0).max(2).default(0),
});

/**
 * 设备模板更新参数验证规则
 * 用于验证更新接口的请求体参数
 * 与创建规则的区别是所有字段都非必填
 */
const updateSchema = Joi.object({
  // 模板名称，最大长度100字符
  name: Joi.string().max(100).message('模板名称长度不超过100字符'),
  // 模板描述，最大长度500字符，允许为空
  description: Joi.string().max(500).allow(null, ''),
  // 设备类型，0-2之间的整数
  equipmentType: Joi.number().integer().min(0).max(2).message('设备类型必须为0-2的整数'),
  // 运动方式，最大长度500字符，允许为空
  modeOfMotion: Joi.string().max(500).allow(null, ''),
  // 运动特性，最大长度500字符，允许为空
  kineticCharacteristic: Joi.string().max(500).allow(null, ''),
  // 运行速度，保留两位小数，允许为空
  runningVelocity: Joi.number().precision(2).allow(null),
  // 载荷性质，最大长度200字符，允许为空
  loadProperty: Joi.string().max(200).allow(null, ''),
  // 周围环境，最大长度200字符，允许为空
  surrounding: Joi.string().max(200).allow(null, ''),
  // 设备等级，最大长度100字符，允许为空
  gradeOfEquipment: Joi.string().max(100).allow(null, ''),
  // 是否有备机，0-2之间的整数
  standby: Joi.number().integer().min(0).max(2),
});

/**
 * 获取当前用户的所有设备模板列表
 * 对应路由：GET /api/equipment-templates/all
 * 权限控制：仅能获取当前登录用户创建的模板
 */
const getAllTemplates = async (req, res, next) => {
  try {
    // 查询当前用户创建的所有设备模板，按创建时间倒序排列
    const templates = await EquipmentTemplate.findAll({
      where: {
        createUserId: req.user.userId, // 核心：数据隔离，仅查询当前用户的数据
      },
      order: [['createTime', 'DESC']],
      // 只查询需要的字段，优化性能
      attributes: ['equipmentTemplateId', 'name', 'description', 'createTime'],
    });

    // 返回成功响应
    return res.status(200).json({
      code: 200,
      message: '获取所有设备模板成功',
      data: templates,
      timestamp: new Date().getTime(),
    });
  } catch (error) {
    // 错误处理：记录错误日志并传递给全局错误处理器
    console.error('获取设备模板列表失败:', error);
    next(error);
  }
};

/**
 * 分页模糊查询当前用户的设备模板列表
 * 对应路由：GET /api/equipment-templates
 * 功能：支持按名称模糊查询、按设备类型精确查询
 * 权限控制：仅能查询当前登录用户创建的模板
 */
const getTemplatesByPage = async (req, res, next) => {
  try {
    // 验证并转换查询参数
    const { error, value } = querySchema.validate(req.query, {
      convert: true, // 自动转换数据类型
      abortEarly: false, // 收集所有验证错误
    });
    if (error) {
      // 格式化验证错误信息
      const errorMsg = error.details.map((detail) => detail.message).join('; ');
      return res.status(400).json({
        code: 400,
        message: `参数验证失败: ${errorMsg}`,
      });
    }

    // 解析分页参数和查询条件
    const { page, pageSize, name, equipmentType } = value;
    const offset = (page - 1) * pageSize; // 计算分页偏移量

    // 构建查询条件：基础条件为当前用户ID
    const where = {
      createUserId: req.user.userId,
    };

    // 添加名称模糊查询条件（如果提供了名称）
    if (name && name.trim()) {
      where.name = { [Op.like]: `%${name.trim()}%` };
    }

    // 执行分页查询：同时获取总数和当前页数据
    const { count, rows } = await EquipmentTemplate.findAndCountAll({
      where,
      limit: pageSize, // 每页条数
      offset, // 偏移量（分页起始位置）
      order: [['createTime', 'DESC']], // 按创建时间倒序排列
      attributes: {
        exclude: [], // 可以指定排除的字段，优化查询性能
      },
    });

    // 计算总页数
    const totalPages = Math.ceil(count / pageSize);

    // 返回分页查询结果
    return res.status(200).json({
      code: 200,
      message: '分页查询设备模板成功',
      data: {
        list: rows, // 当前页数据列表
        total: count, // 总记录数
        page, // 当前页码
        pageSize, // 每页条数
        totalPages, // 总页数
        hasNextPage: page < totalPages, // 是否有下一页
        hasPrevPage: page > 1, // 是否有上一页
      },
      timestamp: new Date().getTime(),
    });
  } catch (error) {
    // 错误处理：记录错误日志并传递给全局错误处理器
    console.error('分页查询设备模板失败:', error);
    next(error);
  }
};

/**
 * 新增设备模板
 * 对应路由：POST /api/equipment-templates
 * 功能：创建新的设备模板，自动关联当前登录用户
 */
const createTemplate = async (req, res, next) => {
  try {
    // 验证请求体参数
    const { error, value } = createSchema.validate(req.body, {
      abortEarly: false, // 收集所有验证错误
    });
    if (error) {
      // 格式化验证错误信息
      const errorMsg = error.details.map((detail) => detail.message).join('; ');
      return res.status(400).json({
        code: 400,
        message: `参数验证失败: ${errorMsg}`,
      });
    }

    // 创建设备模板：自动添加创建者ID和时间戳
    const newTemplate = await EquipmentTemplate.create({
      ...value,
      createUserId: req.user.userId, // 关联当前登录用户
    });

    // 返回创建成功的响应和新创建的模板数据
    return res.status(201).json({
      code: 201,
      message: '设备模板创建成功',
      data: newTemplate,
      timestamp: new Date().getTime(),
    });
  } catch (error) {
    // 处理唯一约束冲突等特定错误
    if (error.name === 'SequelizeUniqueConstraintError') {
      return res.status(409).json({
        code: 409,
        message: '设备模板名称已存在，请更换名称',
        timestamp: new Date().getTime(),
      });
    }

    // 记录错误日志并传递给全局错误处理器
    console.error('创建设备模板失败:', error);
    next(error);
  }
};

/**
 * 更新设备模板
 * 对应路由：PUT /api/equipment-templates/:id
 * 功能：更新指定ID的设备模板
 * 权限控制：仅能更新当前登录用户创建的模板
 */
const updateTemplate = async (req, res, next) => {
  try {
    // 解析并验证路径参数中的模板ID
    const { id } = req.params;
    if (!id || isNaN(Number(id)) || Number(id) <= 0) {
      return res.status(400).json({
        code: 400,
        message: '无效的模板ID，必须是正整数',
      });
    }
    const templateId = Number(id);

    // 验证更新数据
    const { error, value } = updateSchema.validate(req.body, {
      abortEarly: false, // 收集所有验证错误
    });
    if (error) {
      // 格式化验证错误信息
      const errorMsg = error.details.map((detail) => detail.message).join('; ');
      return res.status(400).json({
        code: 400,
        message: `参数验证失败: ${errorMsg}`,
      });
    }

    // 检查模板是否存在且属于当前用户
    const template = await EquipmentTemplate.findOne({
      where: {
        id: templateId,
        createUserId: req.user.userId, // 确保只能更新自己创建的模板
      },
    });
    if (!template) {
      return res.status(404).json({
        code: 404,
        message: '设备模板不存在或没有权限操作',
      });
    }

    // 执行更新：添加更新时间戳
    await template.update({
      ...value,
      updateTime: new Date(), // 更新时间
    });

    // 获取更新后的完整数据
    const updatedTemplate = await EquipmentTemplate.findByPk(templateId);

    // 返回更新成功的响应
    return res.status(200).json({
      code: 200,
      message: '设备模板更新成功',
      data: updatedTemplate,
      timestamp: new Date().getTime(),
    });
  } catch (error) {
    // 处理唯一约束冲突等特定错误
    if (error.name === 'SequelizeUniqueConstraintError') {
      return res.status(409).json({
        code: 409,
        message: '设备模板名称已存在，请更换名称',
        timestamp: new Date().getTime(),
      });
    }

    // 记录错误日志并传递给全局错误处理器
    console.error('更新设备模板失败:', error);
    next(error);
  }
};

/**
 * 删除设备模板
 * 对应路由：DELETE /api/equipment-templates/:id
 * 功能：删除指定ID的设备模板
 * 权限控制：仅能删除当前登录用户创建的模板
 */
const deleteTemplate = async (req, res, next) => {
  try {
    // 解析并验证路径参数中的模板ID
    const { id } = req.params;
    if (!id || isNaN(Number(id)) || Number(id) <= 0) {
      return res.status(400).json({
        code: 400,
        message: '无效的模板ID，必须是正整数',
      });
    }
    const templateId = Number(id);

    // 检查模板是否存在且属于当前用户
    const template = await EquipmentTemplate.findOne({
      where: {
        id: templateId,
        createUserId: req.user.userId, // 确保只能删除自己创建的模板
      },
    });
    if (!template) {
      return res.status(404).json({
        code: 404,
        message: '设备模板不存在或没有权限操作',
      });
    }

    // 执行删除操作
    await template.destroy();

    // 返回删除成功的响应
    return res.status(200).json({
      code: 200,
      message: '设备模板删除成功',
      data: { id: templateId }, // 返回被删除的ID
      timestamp: new Date().getTime(),
    });
  } catch (error) {
    // 处理外键约束错误（如果模板被其他表引用）
    if (error.name === 'SequelizeForeignKeyConstraintError') {
      return res.status(409).json({
        code: 409,
        message: '无法删除该模板，因为它正在被其他资源引用',
        timestamp: new Date().getTime(),
      });
    }

    // 记录错误日志并传递给全局错误处理器
    console.error('删除设备模板失败:', error);
    next(error);
  }
};

/**
 * 根据设备模板编号获取设备模板详情
 * 对应路由：GET /api/equipment-templates/:id
 * 功能：获取指定编号的设备模板详情
 * 权限控制：仅能获取当前登录用户创建的模板
 */
const getTemplateInfo = async (req, res, next) => {
  try {
    // 查询当前用户下指定设备模板编号的设备模板详情
    const templates = await EquipmentTemplate.findOne({
      where: {
        createUserId: req.user.userId,
        equipmentTemplateId: id,
      },
    });

    // 返回成功响应
    return res.status(200).json({
      code: 200,
      message: '获取设备模板详情成功',
      data: templates,
      timestamp: new Date().getTime(),
    });
  } catch (error) {
    // 错误处理：记录错误日志并传递给全局错误处理器
    console.error('获取设备模板列表失败:', error);
    next(error);
  }
};

module.exports = {
  getAllTemplates,
  getTemplatesByPage,
  createTemplate,
  updateTemplate,
  deleteTemplate,
  getTemplateInfo,
};
